package cn.iocoder.yudao.module.scrm.aop;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.module.scrm.dal.dataobject.customer.CustomerDO;
import cn.iocoder.yudao.module.scrm.service.phoneencryptor.PhoneEncryptorService;
import com.fasterxml.jackson.core.type.TypeReference;
import java.lang.reflect.Type;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;

/**
 * @author pg
 * @project zysx
 * @description 加密电话
 * @date 2024/9/6 11:26:01
 */
@Aspect
@Component
@Order(1)
@Slf4j
public class PhoneNumberEncryptorAspect {

    @Resource
    private ObjectMapper objectMapper;

    @Resource
    private PhoneEncryptorService phoneEncryptorService;

    @Around("@annotation(cn.iocoder.yudao.module.scrm.annotations.EncryptPhoneNumbers)")
    public Object encryptPhoneNumbers(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result = joinPoint.proceed();
        if (Boolean.TRUE.equals(phoneEncryptorService.getPhoneEncryptorByUserId(WebFrameworkUtils.getLoginUserId()))) {
            return encryptPhoneNumbersInJson(result, getGenericType(result));
        }
        return result;
    }

    private <T> T encryptPhoneNumbersInJson(T result, Type genericType) {
        try {
            String jsonResult = objectMapper.writeValueAsString(result);
            String encryptedJson = encryptPhoneNumbers(jsonResult);

            // 使用 JavaType 来处理嵌套泛型类型
            JavaType javaType = getJavaType(result.getClass(), genericType);
            return objectMapper.readValue(encryptedJson, javaType);
        } catch (IOException e) {
            throw new RuntimeException("Error while processing JSON encryption", e);
        }
    }

    private String encryptPhoneNumbers(String jsonString) {
        // 正则表达式用于匹配电话号码并进行加密
        String regex = "\"phone\":\"(\\d{3})\\d{4}(\\d{4})\"";
        String replacement = "\"phone\":\"$1****$2\"";
        return jsonString.replaceAll(regex, replacement);
    }

    // 获取泛型类型
    private Type getGenericType(Object result) {
        if (result instanceof PageResult) {
            List<?> list = ((PageResult<?>) result).getList();
            if (!list.isEmpty()) {
                // 如果list不为空，获取list中第一个元素的类型
                return list.get(0).getClass();
            }
        }
        return Object.class;  // 默认返回Object类
    }

    // 构建 JavaType，用于反序列化
    private JavaType getJavaType(Class<?> rawClass, Type genericType) {
        TypeFactory typeFactory = objectMapper.getTypeFactory();

        if (PageResult.class.isAssignableFrom(rawClass)) {
            // 获取 List<T> 的 JavaType
            JavaType innerType = typeFactory.constructType(genericType);
            // 构建 PageResult<T> 的 JavaType
            return typeFactory.constructParametricType(PageResult.class, innerType);
        }

        // 对于其他类型，返回其自身的类型
        return typeFactory.constructType(rawClass);
    }
}